<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: App.class.php 2792 2012-03-02 03:36:36Z liu21st $


/**
 +------------------------------------------------------------------------------
 * ThinkPHP 应用程序类 执行应用过程管理
 * 可以在模式扩展中重新定义 但是必须具有Run方法接口
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Core
 * @author    liu21st <liu21st@gmail.com>
 * @version   $Id: App.class.php 2792 2012-03-02 03:36:36Z liu21st $
 +------------------------------------------------------------------------------
 */
class App {
	
	/**
     +----------------------------------------------------------
	 * 应用程序初始化
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	static public function init() {
		
		// 设置系统时区
		date_default_timezone_set ( C ( 'DEFAULT_TIMEZONE' ) );
		// 加载动态项目公共文件和配置
		load_ext_file ();
		// URL调度
		Dispatcher::dispatch ();
		
		if (defined ( 'GROUP_NAME' )) {
			// 加载分组配置文件
			if (is_file ( CONF_PATH . GROUP_NAME . '/config.php' ))
				C ( include CONF_PATH . GROUP_NAME . '/config.php' );
			
		// 加载分组函数文件
			if (is_file ( COMMON_PATH . GROUP_NAME . '/function.php' ))
				include COMMON_PATH . GROUP_NAME . '/function.php';
		}
		
		/* 获取模板主题名称 */
		$templateSet = C ( 'DEFAULT_THEME' );
		if (C ( 'TMPL_DETECT_THEME' )) { // 自动侦测模板主题
			$t = C ( 'VAR_TEMPLATE' );
			if (isset ( $_GET [$t] )) {
				$templateSet = $_GET [$t];
			} elseif (cookie ( 'think_template' )) {
				$templateSet = cookie ( 'think_template' );
			}
			// 主题不存在时仍改回使用默认主题
			if (! is_dir ( TMPL_PATH . $templateSet ))
				$templateSet = C ( 'DEFAULT_THEME' );
			cookie ( 'think_template', $templateSet );
		}
		/* 模板相关目录常量 */
		define ( 'THEME_NAME', $templateSet ); // 当前模板主题名称
		$group = defined ( 'GROUP_NAME' ) ? GROUP_NAME . '/' : '';
		define ( 'THEME_PATH', TMPL_PATH . $group . (THEME_NAME ? THEME_NAME . '/' : '') );
		define ( 'APP_TMPL_PATH', __ROOT__ . '/' . APP_NAME . (APP_NAME ? '/' : '') . basename ( TMPL_PATH ) . '/' . $group . (THEME_NAME ? THEME_NAME . '/' : '') );
		C ( 'TEMPLATE_NAME', THEME_PATH . MODULE_NAME . (defined ( 'GROUP_NAME' ) ? C ( 'TMPL_FILE_DEPR' ) : '/') . ACTION_NAME . C ( 'TMPL_TEMPLATE_SUFFIX' ) );
		C ( 'CACHE_PATH', CACHE_PATH . $group );
		return;
	}
	
	/**
     +----------------------------------------------------------
	 * 执行应用程序
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 * @throws ThinkExecption
     +----------------------------------------------------------
	 */
	static public function exec() {
		// 安全检测
		if (! preg_match ( '/^[A-Za-z_0-9]+$/', MODULE_NAME )) {
			$module = false;
		} else {
			//创建Action控制器实例
			$group = defined ( 'GROUP_NAME' ) ? GROUP_NAME . '/' : '';
			$module = A ( $group . MODULE_NAME );
		}
		
		if (! $module) {
			if (function_exists ( '__hack_module' )) {
				// hack 方式定义扩展模块 返回Action对象
				$module = __hack_module ();
				if (! is_object ( $module )) {
					// 不再继续执行 直接返回
					return;
				}
			} else {
				// 是否定义Empty模块
				$module = A ( 'Empty' );
				if (! $module) {
					$msg = L ( '_MODULE_NOT_EXIST_' ) . MODULE_NAME;
					if (APP_DEBUG) {
						// 模块不存在 抛出异常
						throw_exception ( $msg );
					} else {
						if (C ( 'LOG_EXCEPTION_RECORD' ))
							Log::write ( $msg );
						send_http_status ( 404 );
						exit ();
					}
				}
			}
		}
		//获取当前操作名
		$action = ACTION_NAME;
		// 获取操作方法名标签
		tag ( 'action_name', $action );
		if (method_exists ( $module, '_before_' . $action )) {
			// 执行前置操作
			call_user_func ( array (&$module, '_before_' . $action ) );
		}
		//执行当前操作
		call_user_func ( array (&$module, $action ) );
		if (method_exists ( $module, '_after_' . $action )) {
			//  执行后缀操作
			call_user_func ( array (&$module, '_after_' . $action ) );
		}
		return;
	}
	
	/**
     +----------------------------------------------------------
	 * 运行应用实例 入口文件使用的快捷方法
     +----------------------------------------------------------
	 * @access public
     +----------------------------------------------------------
	 * @return void
     +----------------------------------------------------------
	 */
	static public function run() {
		// 项目初始化标签
		tag ( 'app_init' );
		App::init ();
		// 项目开始标签
		tag ( 'app_begin' );
		// Session初始化
		session ( C ( 'SESSION_OPTIONS' ) );
		// 记录应用初始化时间
		G ( 'initTime' );
		App::exec ();
		// 项目结束标签
		tag ( 'app_end' );
		// 保存日志记录
		if (C ( 'LOG_RECORD' ))
			Log::save ();
		return;
	}

}